<?php

namespace app\zyhsapi\controller\v1;

use app\aliyun\controller\AliyunFilterWord;
use app\common\lib\Aes;
use app\common\lib\astrolog\Astrolog;
use app\common\lib\Util;
use app\zyhsapi\controller\ZyhsAuth;
use app\zyhsapi\model\ZyhsRecode;
use app\zyhsapi\model\ZyhsRecodeAstro;
use app\zyhsapi\model\ZyhsRecodeSyncRecode;
use app\zyhsapi\model\ZyhsUser;
use app\zyhsapi\service\CacheZyhs;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\DbException;
use think\Log;

class Recode extends ZyhsAuth
{
    protected $setting = [
        'natal' => [
            'planet' => [
                [1, 8.5], [1, 7.5], [1, 3.5], [1, 3.5], [1, 4], [1, 4.5], [1, 4.5], [1, 2.5], [1, 2.5], [1, 2.5],
                [0, 0], [0, 0], [0, 0], [0, 0], [1, 2.5], [0, 0], [0, 0], [1, 2.5], [1, 2.5], [1, 2.5], [1, 2.5]
            ],
            'phase' => [
                0 => [1, 0], 60 => [1, 0], 90 => [1, 0], 120 => [1, 0], 180 => [1, 0],
                45 => [0, 0], 135 => [0, 0], 30 => [0, 0], 150 => [0, 0], 72 => [0, 0], 144 => [0, 0]
            ],
            'arabic' => [
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
                [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
            ],
            'h_sys' => 'p',
            'firdaria' => 'default',
            'bound_type' => 'default',
            'ecliptic' => 0,
            'profection_push_direction' => 0,
            'decanates' => 0,
            'ayanamsa' => 0,
            'location_use' => 0
        ],
    ];

    protected $noNeedJudgeSummer = ['香港特别行政区', '澳门特别行政区', '台湾省', '北美洲', '大洋洲', '非洲', '南美洲', '欧洲', '亚洲', ''];

    public function syncRecode()
    {
        $thirdUidStr = input('uid/s', '');
        $thirdUidStr = (new Aes())->decryptWithOpenssl($thirdUidStr, 'zyhsapp');
        if (!$thirdUidStr)
        {
            return show(config('code.error'), '服务异常，请稍后再试～');
        }
        if (Util::commentCheck($this->user['id'], ['data' => $thirdUidStr], 5))
        {
            return show(config('code.error'), '操作频繁，请稍后再试');
        }
        $thirdData = explode('|', $thirdUidStr);
        if (count($thirdData) !== 3)
        {
            return show(config('code.error'), '服务异常，请稍后再试～');
        }
        $t = $this->request->time() - $thirdData[2];
        if ($t > 1800 || $t <= 0)
        {
            return show(config('code.error'), '服务异常，请稍后再试～');
        }
        $uid = (int)(substr($thirdData[1], 6));
        if ($uid !== $this->user['id'])
        {
            return show(config('code.error'), '服务异常，请稍后再试～');
        }
        $thirdUid = (int)(substr($thirdData[0], 6));

        $syncStatus = CacheZyhs::get('recode_sync:uid' . $this->user['id'], 0);
        if ($syncStatus == 1)
        {
            return show(config('code.error'), '正在同步中，请稍后再试～');
        }
        if ($syncStatus == 2)
        {
            $recordInfo = (new ZyhsRecode())->getRecodeLists($this->user['id'], 1);
            return show(config('code.success'), '同步完成', [
                'self_rid' => $recordInfo ? (int)($recordInfo['id'] ?? 0) : 0,
            ]);
        }
        $recodeSyncRecodeModel = new ZyhsRecodeSyncRecode();
        if ($recodeSyncRecodeModel->getUserIsSync($this->user['id']))
        {
            return show(config('code.error'), '已经同步过档案了，请勿重复操作');
        }
        CacheZyhs::set('recode_sync:uid' . $this->user['id'], 1, 3600); // 1=>同步中
        $res = Util::ZyhsRecordSync($thirdUid, $uid);
        if ($res['status'])
        {
            CacheZyhs::set('recode_sync:uid' . $this->user['id'], 2, 3600); // 2 => 同步完成
            // 添加同步记录
            $recodeSyncRecodeModel->insert([
                'uid' => $this->user['id'],
                'num' => $res['num'],
                'sync_uid' => $thirdUid,
                'create_time' => $this->request->time()
            ]);
            return show(config('code.success'), '请求成功', [
                'self_rid' => $res['self_rid']
            ]);
        } else
        {
            CacheZyhs::rm('recode_sync:uid' . $this->user['id']); // 同步失败 删除缓存
            return show(config('code.error'), '服务异常，请稍后再试～');
        }
    }

    /**
     * 档案列表
     */
    public function lists()
    {
        $id = input('id/d', 0);
        $uid = $this->user['id'];

        if ($id)
        {
            $data = Db::table('good_wechat.zyhs_recode')->alias('r')
                ->join('good_wechat.zyhs_recode_astro ra', 'r.id=ra.rid', 'INNER')
                ->field('r.id,r.name,r.type,r.year,r.month,r.day,r.hour,r.minute,r.timezone,birth_country,birth_province,birth_city,live_country,live_province,live_city,comments,isself,long_deg,long_min,ew,lat_deg,lat_min,ns,avatar,is_summer,uid,aid,sun,moon,merc,venu,mars,jupi,satu,non,lili,juno,asc,mc,r.is_read,r.channel')
                ->where(['r.id' => $id, 'uid' => $uid])
                ->find();
            if (empty($data))
            {
                return show(config('code.error'), '服务异常，档案不存在～');
            }
            $data = [$data];
        } else
        {
            $data = Db::table('good_wechat.zyhs_recode')->alias('r')
                ->join('good_wechat.zyhs_recode_astro ra', 'r.id=ra.rid', 'INNER')
                ->field('r.id,r.name,r.type,r.year,r.month,r.day,r.hour,r.minute,r.timezone,birth_country,birth_province,birth_city,live_country,live_province,live_city,comments,isself,long_deg,long_min,ew,lat_deg,lat_min,ns,avatar,is_summer,uid,aid,sun,moon,merc,venu,mars,jupi,satu,non,lili,juno,asc,mc,r.is_read,r.channel')
                ->where(['uid' => $uid, 'status' => 1])
                ->select();
        }
        $data = (new ZyhsRecode())->dataInit($data);

        return show(config('code.success'), 'success', $data);
    }

    /**
     * 添加档案
     */
    public function add()
    {
        $name = input('name/s', '', 'htmlspecialchars');// 档案名称
        $type = input('type/d');// 档案类型  1男 | 2 女 | 3 男同 | 4 女同 | 5 事件 | 6 卜卦
        $year = input('year/d');// 出生时间-年
        $month = input('month/d');// 出生时间-月
        $day = input('day/d');// 出生时间-日
        $hour = input('hour/d');// 出生时间-时
        $minute = input('minute/d');// 出生时间-分
        $timezone = input('timezone/d', 8);// 出生时间-时区
        $birth_country = input('birth_country/s', '', 'htmlspecialchars');// 出生地点-省
        $birth_province = input('birth_province/s', '', 'htmlspecialchars');// 出生地点-市
        $birth_city = input('birth_city/s', '', 'htmlspecialchars');// 出生地点-区
        $live_country = input('live_country/s', '', 'htmlspecialchars');// 现居地-省
        $live_province = input('live_province/s', '', 'htmlspecialchars');// 现居地-省
        $live_city = input('live_city/s', '', 'htmlspecialchars');// 现居地-省
        $comments = input('comments/s', '', 'htmlspecialchars');// 档案标签如 自己 朋友 案例
        $isself = input('isself/d', 0);// 档案是否为自己 0 否 | 1 是（自己的档案无法删除，无法更改为其他标签）
        $long_deg = input('long_deg/d');// 经度-度
        $long_min = input('long_min/d');// 经度-分
        $ew = input('ew/d');// 东经|西经 1|-1
        $lat_deg = input('lat_deg/d');// 纬度-度
        $lat_min = input('lat_min/d');// 纬度-分
        $ns = input('ns/d');// 南纬北纬  1|-1
        $avatar = input('avatar/s', '', 'htmlspecialchars');// 头像地址

        $is_summer = 0;
        $name = str_replace(["\r\n", "\r", "\n"], "", $name);
        // 只判断大陆地区的夏令时
        if (!in_array($birth_country, $this->noNeedJudgeSummer, true))
        {
            $is_summer = isSummerTime($hour, $minute, 0, $month, $day, $year) ? 1 : 0;// 是否开启夏令时
        }
        if (($isself === 1 && $comments !== '自己') || ($comments === '自己' && $isself !== 1))
        {
            return show(config('code.error'), '服务异常，请稍后重试');
        }

        $uid = $this->user['id'];
        $data = [
            'uid' => $uid,
            'name' => $name,
            'type' => $type,
            'year' => $year,
            'month' => $month,
            'day' => $day,
            'hour' => $hour,
            'minute' => $minute,
            'timezone' => $timezone,
            'birth_country' => $birth_country,
            'birth_province' => $birth_province,
            'birth_city' => $birth_city,
            'live_country' => $live_country,
            'live_province' => $live_province,
            'live_city' => $live_city,
            'comments' => $comments,
            'isself' => $isself,
            'long_deg' => $long_deg,
            'long_min' => $long_min,
            'ew' => $ew,
            'lat_deg' => $lat_deg,
            'lat_min' => $lat_min,
            'ns' => $ns,
            'avatar' => $avatar,
            'is_summer' => $is_summer,
        ];
        $validate = validate('Recode');
        if (!$validate->scene('add')->check($data))
        {
            return show(config('code.error'), (string)$validate->getError());
        }

        $time = time();
        $RecodeCacheModel = new ZyhsRecode();
        // 查询当前星盘日月水金火木土等星落座落宫存入数据库
        $astro_data = Astrolog::getInstance()->setExecPrefix(config('astrolog.prefix'))
            ->setIsAstrolabe(false)
            ->setRecode1($data)
            ->setUserSetting($this->setting)
            ->getTheRecodeAstro();

        // 仅检测自己的档案，其他人的档案由于其他人看不到，所以不校验
        if ($data['isself'] === 1)
        {
            $res = AliyunFilterWord::checkText($name, 'username');
            //若内容有违规且超过配置的相似比例，则进行隐藏不显示，将标签存入库中
            if ($res)
            {
                return show(0, '昵称涉嫌' . $res['label'] . '，请重新设置');
            }
        }

        // 查询是否为自己 覆盖已有的记录 20180814
        if ($comments === '自己' && $isself === 1 && $this->isself($uid))
        {
            $recode_old = $RecodeCacheModel->getRecodeLists($this->user['id'], 1);
            if (empty($recode_old))
            {
                return json(['code' => 10304, 'msg' => 'Recode is not exist.']);
            }
            if (empty($data['avatar']))
            {
                $data['avatar'] = $this->user['avatar'];
            }

            $result = $RecodeCacheModel->UpdateData($uid, $recode_old['id'], $data);

            $data['id'] = $recode_old['id'];// 返回档案id
            if ($result === false)
            {
                return show(config('code.error'), '档案不存在');
            }

            //删除用户缓存
            (new ZyhsUser())->updateUserinfo(['id' => $this->user['id']], ['nickname' => $name, 'username' => $name, 'avatar' => $avatar, 'has_self_recode' => 1]);

            (new ZyhsRecodeAstro())->where(['id' => $recode_old['aid']])->update($astro_data);// 更新档案行星数据
        } else
        {
            if ($data['comments'] === '自己' && $data['isself'] === 1)
            {
                if ($data['avatar'])
                {
                    $avatar = $data['avatar'];
                } else
                {
                    $avatar = $data['avatar'] = $this->user['avatar'];
                }
            }
            $rid = $RecodeCacheModel->SaveData($uid, $data);
            if (!$rid)
            {
                return show(config('code.error'), '保存失败');
            }

            if ($data['comments'] === '自己' && $data['isself'] === 1)
            {
                //删除用户缓存
                (new ZyhsUser())->updateUserinfo(['id' => $this->user['id']], ['nickname' => $name, 'username' => $name, 'avatar' => $avatar, 'has_self_recode' => 1]);
            }

            $astro_data['rid'] = $rid;
            $astro_data['create_time'] = $time;

            Db::table('good_wechat.zyhs_recode_info')->insertGetId(['rid' => $rid, 'create_time' => $time, 'last_time' => $time]);// 新增当前档案访问数据

            $aid = (new ZyhsRecodeAstro())->insertGetId($astro_data);// 新增当前档案行星数据
            $data['id'] = $rid;
            $RecodeCacheModel->UpdateData($uid, $rid, ['aid' => $aid]);
        }
        //返回is_read=1写死【Android需要返回】（0：未读，显示new；1：已读）
        $data['is_read'] = 1;

        return show(config('code.success'), '请求成功', array_merge($data, $astro_data));
    }

    /**
     * 档案编辑
     */
    public function update()
    {
        $data = [
            'id' => input('id/d'),// 档案id
            'uid' => $this->user['id'],// 用户id
            'name' => input('name/s', '', 'htmlspecialchars'),// 档案名称
            'type' => input('type/d'),// 档案类型  1男 | 2 女 | 3 男同 | 4 女同 | 5 事件 | 6 卜卦
            'year' => input('year/d'),// 出生时间-年
            'month' => input('month/d'),// 出生时间-月
            'day' => input('day/d'),// 出生时间-日
            'hour' => input('hour/d'),// 出生时间-时
            'minute' => input('minute/d'),// 出生时间-分
            'timezone' => input('timezone/d', 8),// 出生时间-时区
            'birth_country' => input('birth_country/s', '', 'htmlspecialchars'),// 出生地点-省
            'birth_province' => input('birth_province/s', '', 'htmlspecialchars'),// 出生地点-市
            'birth_city' => input('birth_city/s', '', 'htmlspecialchars'),// 出生地点-区
            'live_country' => input('live_country/s', '', 'htmlspecialchars'),// 现居地-省
            'live_province' => input('live_province/s', '', 'htmlspecialchars'),// 现居地-省
            'live_city' => input('live_city/s', '', 'htmlspecialchars'),// 现居地-省
            'comments' => input('comments/s', '', 'htmlspecialchars'),// 档案标签如 自己 朋友 案例
            'isself' => input('isself/d', 0),// 档案是否为自己 0 否 | 1 是（自己的档案无法删除，无法更改为其他标签）
            'long_deg' => input('long_deg/d'),// 经度-度
            'long_min' => input('long_min/d'),// 经度-分
            'ew' => input('ew/d'),// 东经|西经 1|-1
            'lat_deg' => input('lat_deg/d'),// 纬度-度
            'lat_min' => input('lat_min/d'),// 纬度-度
            'ns' => input('ns/d'),// 南纬北纬  1|-1
            'avatar' => input('avatar/s', '', 'htmlspecialchars'),// 头像地址
            'status' => 1,// 档案状态
            'from' => 'zhunle',// 档案来源
            'is_summer' => 0 // 默认为不开启夏令时
        ];
        $data['name'] = str_replace(["\r\n", "\r", "\n"], "", $data['name']);
        // 只判断大陆地区的夏令时
        if (!in_array($data['birth_country'], $this->noNeedJudgeSummer, true))
        {
            $data['is_summer'] = isSummerTime($data['hour'], $data['minute'], 0, $data['month'], $data['day'], $data['year']) ? 1 : 0;// 是否开启夏令时
        }

        if (($data['isself'] === 1 && $data['comments'] !== '自己') || ($data['comments'] === '自己' && $data['isself'] !== 1))
        {
            return show(config('code.error'), '服务异常，请稍后重试');
        }

        $recodeModel = new ZyhsRecode();
        $validate = validate('Recode');

        if (!$validate->scene('edit')->check($data))
        {
            return show(config('code.error'), (string)$validate->getError());
        }

        // 查询未更改前的档案
        $recode_old = $recodeModel->getInfoById($data['id']);

        if (!$recode_old || $recode_old['uid'] != $this->user['id'] || !$recode_old['status'])
        {
            return show(config('code.error'), '档案不存在');
        }

        if ($recode_old['isself'] != 1 && $data['isself'] === 1 && ($this->user['rid'] && $this->user['rid'] != $data['id']))
        {
            return show(config('code.error'), '不能添加多个自己的档案');
        }

        // 检测档案编辑是否更改时间
        $timeChange = false;// 默认表示时间未进行更新
        $old_time = strtotime($recode_old['year'] . '-' . $recode_old['month'] . '-' . $recode_old['day'] . ' ' . $recode_old['hour'] . ':' . $recode_old['minute']);
        $new_time = strtotime($data['year'] . '-' . $data['month'] . '-' . $data['day'] . ' ' . $data['hour'] . ':' . $data['minute']);
        // 时间有变动
        if ($old_time != $new_time || $recode_old['timezone'] != $data['timezone'] || $recode_old['is_summer'] != $data['is_summer'])
        {
            $timeChange = true;
        }
        // 检测档案编辑是否更改出生地经纬度
        $old_longitude = ($recode_old['long_deg'] + $recode_old['long_min'] / 60) * $recode_old['ew'];
        $old_latitude = ($recode_old['lat_deg'] + $recode_old['lat_min'] / 60) * $recode_old['ns'];
        $new_longitude = ($data['long_deg'] + $data['long_min'] / 60) * $data['ew'];
        $new_latitude = ($data['lat_deg'] + $data['lat_min'] / 60) * $data['ns'];

        $longLatChange = false;

        if ($old_longitude != $new_longitude || $old_latitude != $new_latitude)
        {
            $longLatChange = true;
        }
        try
        {
            // 查询当前星盘日月水金火木土等星落座落宫存入数据库
            $astro_data = Astrolog::getInstance()->setExecPrefix(config('astrolog.prefix'))
                ->setIsAstrolabe(false)
                ->setRecode1($data)
                ->setUserSetting($this->setting)
                ->getTheRecodeAstro();

            // 仅检测自己的档案，其他人的档案由于其他人看不到，所以不校验
            if ($data['isself'] === 1)
            {
                $res = AliyunFilterWord::checkText($data['name'], 'username');
                //若内容有违规且超过配置的相似比例，则进行隐藏不显示，将标签存入库中
                if ($res)
                {
                    return show(0, '昵称涉嫌' . $res['label'] . '，请重新设置');
                }
            }
            $data['sun'] = $astro_data['sun'];
            $data['moon'] = $astro_data['moon'];
            $data['asc'] = $astro_data['asc'];
            $data['merc'] = $astro_data['merc'];
            $data['venu'] = $astro_data['venu'];
            $data['mars'] = $astro_data['mars'];
            $data['jupi'] = $astro_data['jupi'];
            $data['satu'] = $astro_data['satu'];
            $data['non'] = $astro_data['non'];
            $data['lili'] = $astro_data['lili'];
            $data['juno'] = $astro_data['juno'];
            $data['mc'] = $astro_data['mc'];
            // 更新档案数据
            $recodeModel->UpdateData($this->user['id'], $data['id'], $data);
            // 如果更新的是自己的档案 且 用户修改了档案名称或头像 则更新用户数据 昵称 头像
            if ($recode_old['isself'] == 1 && ($data['name'] != $recode_old['name'] || $data['avatar'] != $recode_old['avatar']))
            {
                (new ZyhsUser())->updateUserinfo(['id' => $data['uid']], ['nickname' => $data['name'], 'avatar' => $data['avatar']]);
            } elseif ($recode_old['isself'] != 1 && $data['isself'] == 1)
            {  // 如果旧档案不是自己 改为了自己
                (new ZyhsUser())->updateUserinfo(['id' => $data['uid']], ['nickname' => $data['name'], 'avatar' => $data['avatar']]);
            }
            // 更新档案行星数据
            if ($timeChange || $longLatChange)
            {
                // 记录用户更新档案的时间
                Db::table('good_wechat.zyhs_recode_info')->where('rid', $data['id'])->update(['last_time' => time()]);
                // 更新用户档案档案信息 行星落座信息
                (new ZyhsRecodeAstro())->where(['id' => $recode_old['aid']])->update($astro_data);
            }
            $data['aid'] = $recode_old['aid'];
        }
        catch (\Exception $e)
        {
            Log::write('编辑档案失败：' . $e->getMessage(), 'edit_recode_error', true);

            return show(config('code.error'), '更新失败');
        }
        //返回is_read=1写死【Android需要返回】（0：未读，显示new；1：已读）
        $data['is_read'] = 1;
        return show(config('code.success'), '更新成功', array_merge($data, $astro_data));
    }

    /**
     * 删除档案
     * @return mixed
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function delete()
    {
        $id = input('id/d', 0);// 档案id

        $uid = $this->user['id'];

        $validate = validate('Recode');

        if (!$validate->scene('del')->check(['id' => $id, 'uid' => $uid]))
        {
            return show(config('code.error'), (string)$validate->getError());
        }
        $recodeModel = new ZyhsRecode();
        // 查询档案
        $data = $recodeModel->getInfoById($id);

        if (empty($data) || !$data['status'])
        {
            return show(config('code.success'), '档案不存在');
        } elseif ($data['uid'] != $this->user['id'])
        {
            return show(config('code.success'), '档案不存在');
        }

        try
        {
//            // 检测档案是否有合盘记录--并给记录做标记
//            (new AppSynastryResult())->recodeDel($id, $uid);
            // 删除档案在档案袋中的信息
            Db::table('good_wechat.zyhs_recode_cat')->where('rid', $id)->delete();
            // 删除档案
            $recodeModel->DelData($uid, $id, ['status' => 0], $data['isself']);

            if ($data['isself'] == 1)
            {   // 自己的档案
                (new ZyhsUser())->updateUserinfo(['id' => $this->user['id']], ['has_self_recode' => 0]);
            }
        }
        catch (\Exception $e)
        {
            return show(config('code.error'), '删除失败');
        }

        return show(config('code.success'), '删除成功');
    }

    /**
     * 查询是否已有标签为自己的档案
     * @param int $uid
     * @param int $id
     * @return bool
     */
    private function isself($uid = 0, $id = 0)
    {
        if ($id)
        {
            $data = Db::table('good_wechat.zyhs_recode')->where(['isself' => 1, 'comments' => '自己', 'uid' => $uid, 'status' => 1, 'id' => ['neq', $id]])->find();
        } else
        {
            $data = Db::table('good_wechat.zyhs_recode')->where(['isself' => 1, 'comments' => '自己', 'status' => 1, 'uid' => $uid])->find();
        }

        if (!empty($data)) return true;

        return false;
    }
}
